package org.apache.solr.search;

import org.apache.lucene.queryparser.surround.query.*;
import org.apache.lucene.search.Query;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.request.SolrQueryRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Plugin for lucene/contrib Surround query parser, bringing SpanQuery supportto Solr
 * 
 * <queryParser name="surround"
 * class="org.apache.solr.search.SurroundQParserPlugin" />
 * 
 * Examples of query syntax can be found in lucene/queryparser/docs/surround
 * 
 * Note that the query string is not analyzed in any way
 * 
 * @since 4.0
 */

public class SurroundQParserPlugin extends QParserPlugin {

    public static String NAME = "surround";

    @Override
    public void init(NamedList args) {
    }

    @Override
    public QParser createParser(String qstr, SolrParams localParams,
            SolrParams params, SolrQueryRequest req) {
        return new SurroundQParser(qstr, localParams, params, req);
    }
}

class SurroundQParser extends QParser {

    protected static final Logger LOG = LoggerFactory.getLogger(SurroundQParser.class);
    static final int DEFMAXBASICQUERIES = 1000;
    static final String MBQParam = "maxBasicQueries";
    String sortStr;
    SolrQueryParser lparser;
    int maxBasicQueries;

    public SurroundQParser(String qstr, SolrParams localParams, SolrParams params, SolrQueryRequest req) {
        super(qstr, localParams, params, req);
    }

    @Override
    public Query parse() throws org.apache.lucene.queryparser.classic.ParseException {

        SrndQuery sq;
        String qstr = getString();
        if (qstr == null) {
            return null;
        }
        String mbqparam = getParam(MBQParam);
        if (mbqparam == null) {
            this.maxBasicQueries = DEFMAXBASICQUERIES;
        }
        else {
            try {
                this.maxBasicQueries = Integer.parseInt(mbqparam);
            }
            catch (Exception e) {
                LOG.warn("Couldn't parse maxBasicQueries value " + mbqparam + ", using default of 1000");
                this.maxBasicQueries = DEFMAXBASICQUERIES;
            }
        }
        // ugh .. colliding ParseExceptions
        try {
            sq = org.apache.lucene.queryparser.surround.parser.QueryParser.parse(qstr);
        }
        catch (org.apache.lucene.queryparser.surround.parser.ParseException pe) {
            throw new org.apache.lucene.queryparser.classic.ParseException(pe.getMessage());
        }

        // so what do we do with the SrndQuery ??
        // processing based on example in LIA Ch 9
        BasicQueryFactory bqFactory = new BasicQueryFactory(this.maxBasicQueries);
        String defaultField = QueryParsing.getDefaultField(getReq().getSchema(), getParam(CommonParams.DF));
        Query lquery = sq.makeLuceneQueryField(defaultField, bqFactory);
        return lquery;
    }
}
